﻿using CLDataAppManagement;
using NationalInstruments.TestStand.Interop.API;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CLDataAppManagementTS
{
    public class DataAppManagementTS
    {
        private static DataAppManagement dataAppManagement = new DataAppManagement();

        /// <summary>
        /// 从本地读取数据到TS
        /// </summary>
        /// <param name="strucVar">TS数据结构</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="errorCode">错误信息</param>
        /// <param name="errorText">错误信息</param>
        public static void ReadDataFromFile(PropertyObject strucVar, string filePath, out int ErrorCode, out string ErrorText, out bool Occurred)
        {
            ErrorCode = 0;
            ErrorText = "NoError";
            Occurred = false;
            try
            {
                dataAppManagement = new DataAppManagement(filePath);
                string js = dataAppManagement.LoadJsonFromFile(filePath, out ErrorCode, out ErrorText).ToString();
                if (ErrorCode == -1)
                {
                    Occurred = true;
                    return;
                }
                Binding(js, strucVar, out ErrorCode, out ErrorText, out Occurred);
                if (ErrorCode == -1)
                {
                    Occurred = true;
                    return;
                }
            }
            catch (Exception ex)
            {
                Occurred = true;
                ErrorCode = -1;
                ErrorText = "读取文件失败！" + ex.Message;
            }
        }
        /// <summary>
        /// 保存数据到本地
        /// </summary>
        /// <param name="strucVar">TS数据结构</param>
        /// <param name="filePath">保存到本地的路径</param>
        /// <param name="errorCode">错误信息</param>
        /// <param name="errorText">错误信息</param>
        public static void WriteDataToFile(PropertyObject strucVar, string filePath, out int ErrorCode, out string ErrorText, out bool Occurred)
        {
            ErrorCode = 0;
            ErrorText = "No Error";
            Occurred = false;
            try
            {
                //判断第一个子节点是否为Root节点
                if (strucVar.GetSubProperties("", 0)[0].Name.ToLower() == "root")
                {
                    //处理Root节点下数据
                    Traverse(strucVar.GetSubProperties("", 0)[0], filePath, out ErrorCode, out ErrorText, out Occurred);
                    if (ErrorCode == -1)
                    {
                        Occurred = true;
                        return;
                    }
                }
                //当前节点的为Root节点
                else if (strucVar.Name.ToLower() == "root")
                {
                    Traverse(strucVar, filePath, out ErrorCode, out ErrorText, out Occurred);
                    if (ErrorCode == -1)
                    {
                        Occurred = true;
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                Occurred = true;
                ErrorCode = -1;
                ErrorText = "写入文件失败！" + ex.Message ;
            }

        }

        /// <summary>
        /// 本地数据读取绑定到TS中
        /// </summary>
        /// <param name="strJson">json字符串</param>
        /// <param name="strucVar">TS数据结构</param>
        /// <param name="errorCode">错误信息</param>
        /// <param name="errorText">错误信息</param>
        private static void Binding(string strJson, PropertyObject strucVar, out int ErrorCode, out string ErrorText, out bool Occurred)
        {
            ErrorCode = 0;
            ErrorText = "No Error";
            Occurred = false;
            try
            {
                if (IsJOjbect(strJson))
                {
                    JObject jo = (JObject)JsonConvert.DeserializeObject(strJson);
                    foreach (var joitem in jo)
                    {
                        if (joitem.Value.GetType() == typeof(JObject))
                        {
                            //注释：存储多国语言信息
                            //if (joitem.Key == "Comments")
                            if (joitem.Key.Contains("#"))
                            {
                                continue;
                            }
                            var type = joitem.Value.Type.ToString();
                            if (type != "Object")
                            {
                                //判断是否可以新增节点
                                strucVar.ValidateNewSubPropertyName(joitem.Key, false, out bool canValid);
                                if (canValid)
                                {
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_String, false, "", 0);
                                }
                            }
                            else
                            {
                                //判断是否可以新增节点
                                strucVar.ValidateNewSubPropertyName(joitem.Key, false, out bool canValid);
                                if (canValid)
                                {
                                    //Value是Object就有子层级，在TS建Container                                                                   
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_Container, false, "", 0);
                                }
                            }
                            //递归
                            Binding(joitem.Value.ToString(), strucVar.GetPropertyObject(joitem.Key, 0), out ErrorCode, out ErrorText, out Occurred);
                            if (ErrorCode == -1)
                            {
                                Occurred = true;
                                return;
                            }
                        }
                        else if (joitem.Value.GetType() == typeof(JValue))
                        {
                            //判断是否可以新增节点
                            strucVar.ValidateNewSubPropertyName(joitem.Key, false, out bool canValid);
                            //判断数据类型
                            if (joitem.Value.Type.ToString() == JValueType.String.ToString())
                            {
                                if (canValid)
                                {
                                    //TS中创建新的子级
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_String, false, "", 0);
                                }
                                //获取子级
                                PropertyObject p = strucVar.GetPropertyObject(joitem.Key, 0);
                                //设置数据
                                p.SetValString("", 0, joitem.Value.ToString());
                            }
                            else if (joitem.Value.Type.ToString() == JValueType.Integer.ToString())
                            {
                                if (canValid)
                                {
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_Number, false, "", 0);
                                }
                                PropertyObject p = strucVar.GetPropertyObject(joitem.Key, 0);
                                p.SetValNumber("", 0, Convert.ToInt32(joitem.Value));
                            }
                            else if (joitem.Value.Type.ToString() == JValueType.Boolean.ToString())
                            {
                                if (canValid)
                                {
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_Boolean, false, "", 0);
                                }
                                PropertyObject p = strucVar.GetPropertyObject(joitem.Key, 0);
                                p.SetValBoolean("", 0, Convert.ToBoolean(joitem.Value));
                            }
                            else if (joitem.Value.Type.ToString() == JValueType.Float.ToString())
                            {
                                if (canValid)
                                {
                                    strucVar.NewSubProperty(joitem.Key, PropertyValueTypes.PropValType_Number, false, "", 0);
                                }
                                PropertyObject p = strucVar.GetPropertyObject(joitem.Key, 0);
                                p.SetValNumber("", 0, Convert.ToDouble(joitem.Value));
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = ex.Message;
                Occurred = true;
            }
        }

        /// <summary>
        /// 获取所有节点名称和节点对象
        /// </summary>
        /// <param name="strucVar"></param>
        /// <param name="inStr"></param>
        /// <returns></returns>
        private static Dictionary<string, PropertyObject> GetFields(PropertyObject strucVar, string inStr)
        {
            Dictionary<string, PropertyObject> dicPropertyObjects = new Dictionary<string, PropertyObject>();
            PropertyObject[] propertyObjects = strucVar.GetSubProperties("", 0);
            string rootName = strucVar.Name;
            //遍历子节点
            for (int i = 0; i < propertyObjects.Length; i++)
            {
                //节点类型
                PropertyObjectType _type = propertyObjects[i].Type;
                //类型名称
                string _typeName = _type.DisplayString;
                string s = _typeName.Split('[')[0];
                //是否为container，不为container则存放有数据
                if (s != "Container")
                {
                    if (inStr != "")
                    {
                        dicPropertyObjects.Add(inStr + "." + propertyObjects[i].Name, propertyObjects[i]);
                    }
                    //inStr为空，则是第一次输入，表示是根节点
                    else
                    {
                        dicPropertyObjects.Add(rootName + "." + propertyObjects[i].Name, propertyObjects[i]);
                    }
                }
            }
            return dicPropertyObjects;
        }
        private static Dictionary<string, PropertyObject> GetContainers(PropertyObject strucVar, string inStr)
        {
            Dictionary<string, PropertyObject> dicPropertyObjects = new Dictionary<string, PropertyObject>();
            PropertyObject[] propertyObjects = strucVar.GetSubProperties("", 0);
            string rootName = strucVar.Name;
            for (int i = 0; i < propertyObjects.Length; i++)
            {
                PropertyObjectType _type = propertyObjects[i].Type;
                string _typeName = _type.DisplayString;
                string s = _typeName.Split('[')[0];
                if (s == "Container")
                {
                    if (inStr != "")
                    {
                        dicPropertyObjects.Add(inStr + "." + propertyObjects[i].Name, propertyObjects[i]);
                    }
                    else if (inStr == "")
                    {
                        dicPropertyObjects.Add(rootName + "." + propertyObjects[i].Name, propertyObjects[i]);
                    }
                }
            }
            return dicPropertyObjects;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="strucVar"></param>
        /// <param name="path"></param>
        /// <param name="ErrorCode"></param>
        /// <param name="ErrorText"></param>
        /// <param name="mainStr"></param>
        private static void Traverse(PropertyObject strucVar, string path, out int ErrorCode, out string ErrorText, out bool Occurred, string mainStr = "")
        {
            ErrorCode = 0;
            ErrorText = "No Error";
            Occurred = false;
            try
            {
                //获取所有非Container子节点
                Dictionary<string, PropertyObject> retDicPropertyObjects_Filed = GetFields(strucVar, mainStr);
                //遍历字典  通过key获取存放的对应的PropertyObject对象
                foreach (var key in retDicPropertyObjects_Filed.Keys)
                {
                    PropertyObjectType _type = retDicPropertyObjects_Filed[key].Type;
                    string _typeName = _type.DisplayString;
                    string s = _typeName.Split('[')[0];
                    if (s == "Number")
                    {
                        var value_num = retDicPropertyObjects_Filed[key].GetValNumber("", 0);
                        dataAppManagement.jsonPath = path;
                        dataAppManagement.ModifyValue(key, value_num, out ErrorCode, out ErrorText);
                        if (ErrorCode == -1)
                        {
                            Occurred = true;
                            return;
                        }
                    }
                    else if (s == "Boolean")
                    {
                        var value_bool = retDicPropertyObjects_Filed[key].GetValBoolean("", 0);
                        dataAppManagement.jsonPath = path;
                        dataAppManagement.ModifyValue(key, value_bool, out ErrorCode, out ErrorText);
                        if (ErrorCode == -1)
                        {
                            Occurred = true;
                            return;
                        }
                    }
                    else if (s == "String")
                    {
                        var value_str = retDicPropertyObjects_Filed[key].GetValString("", 0);
                        dataAppManagement.jsonPath = path;
                        dataAppManagement.ModifyValue(key, value_str, out ErrorCode, out ErrorText);
                        if (ErrorCode == -1)
                        {
                            Occurred = true;
                            return;
                        }
                    }

                }
                //获取所有Container子节点
                Dictionary<string, PropertyObject> retDicPropertyObjects_Container = GetContainers(strucVar, mainStr);
                foreach (var key in retDicPropertyObjects_Container.Keys)
                {
                    Traverse(retDicPropertyObjects_Container[key], path, out ErrorCode, out ErrorText, out Occurred, key);
                    if (ErrorCode == -1)
                    {
                        Occurred = true;
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "存储参数失败！" + ex.Message ;
                Occurred = true;
            }
        }

        private static bool IsJOjbect(string value)
        {
            try
            {
                JObject ja = JObject.Parse(value);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private enum JValueType
        {
            Integer,
            Float,
            String,
            Boolean
        }

    }
}
